using System;
using System.Collections;
using System.Collections.Generic;
using BitMango.Diagnostics;
using UnityEngine;

public class BMPool : ScriptableObject
{
	public static BMPool Instance
	{
		get
		{
			if (BMPool.instance == null)
			{
				BMPool.instance = (Resources.Load("BMPoolSetting") as BMPool);
				if (BMPool.instance == null)
				{
					BMPool.instance = ScriptableObject.CreateInstance<BMPool>();
				}
				if (Application.isPlaying)
				{
					BMPool.instance.Initialize();
				}
			}
			return BMPool.instance;
		}
	}

	private void OnEnable()
	{
		UnityEngine.Object.DontDestroyOnLoad(this);
	}

	private IEnumerator CoRecycle()
	{
		for (;;)
		{
			yield return null;
			while (this.prepareQueue.Count > 0)
			{
				this.prepareQueue.Dequeue().State = RECYCLE_STATE.PREPARED;
			}
		}
		yield break;
	}

	public static bool Contains(string itemName)
	{
		return BMPool.Instance._Contains(itemName);
	}

	public static void WarmUpItem(string itemName, int count)
	{
		BMPool.Instance._WarmUpItem(itemName, count);
	}

	public static GameObject GetItem(string itemName, Transform parent = null)
	{
		return BMPool.Instance._GetItem(itemName, parent);
	}

	public static T GetItem<T>(string itemName, Transform parent = null) where T : Component
	{
		return BMPool.Instance._GetItem<T>(itemName, parent);
	}

	public static List<GameObject> GetUsingItems(string itemName = null)
	{
		return BMPool.Instance._GetUsingItems(itemName);
	}

	public static List<GameObject> GetUsingItems<T>(string itemName = null) where T : MonoBehaviour
	{
		return BMPool.Instance._GetUsingItems<T>(itemName);
	}

	public static bool IsOccupied(GameObject go)
	{
		BMRecycler component = go.GetComponent<BMRecycler>();
		if (component == null)
		{
			UnityEngine.Debug.LogError("Can't manage GameObject - " + go.name);
			return false;
		}
		return component.State == RECYCLE_STATE.OCCUPIED;
	}

	public static void Abandon(GameObject go)
	{
		BMRecycler component = go.GetComponent<BMRecycler>();
		Debugger.Assert(component != null, go.name + " is not 'BMRecycler' item");
		BMPool.Instance._Abandon(component);
	}

	public static void Clear()
	{
		BMPool.Instance._Clear();
	}

	public void Initialize()
	{
		if (BMPool.initialized)
		{
			return;
		}
		if (this.prefabs != null)
		{
			foreach (GameObject gameObject in this.prefabs)
			{
				if (!(gameObject == null))
				{
					BMRecycler component = gameObject.GetComponent<BMRecycler>();
					Debugger.Assert(component != null, gameObject.name + " has not 'BMRecycler'");
					this.molds.Add(gameObject.name.ToLower(), gameObject);
					this.pools.Add(gameObject.name.ToLower(), new List<BMRecycler>());
				}
			}
		}
		TaskManager.StartCoroutine(this.CoRecycle());
		BMPool.initialized = true;
	}

	private bool _Contains(string itemName)
	{
		return this.molds.ContainsKey(itemName.ToLower());
	}

	private void _WarmUpItem(string itemName, int count)
	{
		this.CheckMold(itemName, null);
		Debugger.Assert(this._Contains(itemName), "Can't find item - " + itemName);
		List<BMRecycler> list = this.pools[itemName.ToLower()];
		if (list.Count >= count)
		{
			return;
		}
		int num = count - list.Count;
		for (int i = 0; i < num; i++)
		{
			GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this.molds[itemName.ToLower()]);
			gameObject.name = itemName + "_" + i.ToString();
			BMRecycler component = gameObject.GetComponent<BMRecycler>();
			component.Release();
			list.Add(component);
		}
	}

	private GameObject GetMold(string itemName)
	{
		if (!this._Contains(itemName))
		{
			GameObject gameObject = Resources.Load(this.prefabPath + "/" + itemName, typeof(GameObject)) as GameObject;
			Debugger.Assert(gameObject != null, "Can't load resource - " + itemName);
			this.molds.Add(itemName.ToLower(), gameObject);
			this.pools.Add(itemName.ToLower(), new List<BMRecycler>());
		}
		return this.molds[itemName.ToLower()];
	}

	private void CheckMold(string itemName, Transform parent = null)
	{
		itemName = itemName.ToLower();
		if (!this.molds.ContainsKey(itemName))
		{
			GameObject gameObject = Resources.Load(this.prefabPath + "/" + itemName) as GameObject;
			Debugger.Assert(gameObject != null, this.prefabPath + "/" + itemName + " is not located");
			GameObject gameObject2 = UnityEngine.Object.Instantiate<GameObject>(gameObject);
			gameObject2.SetActive(false);
			gameObject2.name = itemName;
			if (parent != null)
			{
				gameObject2.transform.parent = parent;
			}
			this.molds.Add(itemName, gameObject2);
			this.pools.Add(itemName, new List<BMRecycler>());
		}
	}

	private GameObject _GetItem(string itemName, Transform parent = null)
	{
		GameObject gameObject = null;
		this.CheckMold(itemName, parent);
		Debugger.Assert(BMPool.Contains(itemName), "Can't find item - " + itemName);
		List<BMRecycler> list = this.pools[itemName.ToLower()];
		foreach (BMRecycler bmrecycler in list)
		{
			if (bmrecycler.IsPrepared)
			{
				gameObject = bmrecycler.gameObject;
				break;
			}
		}
		BMRecycler component;
		if (gameObject == null)
		{
			gameObject = UnityEngine.Object.Instantiate<GameObject>(this.molds[itemName.ToLower()]);
			gameObject.name = itemName;
			component = gameObject.GetComponent<BMRecycler>();
			list.Add(component);
		}
		else
		{
			component = gameObject.GetComponent<BMRecycler>();
		}
		if (parent != null)
		{
			gameObject.transform.parent = parent;
		}
		component.Reset();
		component.State = RECYCLE_STATE.OCCUPIED;
		return gameObject;
	}

	private T _GetItem<T>(string itemName, Transform parent = null) where T : Component
	{
		GameObject gameObject = this._GetItem(itemName, parent);
		if (gameObject == null)
		{
			return (T)((object)null);
		}
		return gameObject.GetComponent<T>();
	}

	private List<GameObject> _GetUsingItems(string itemName)
	{
		List<GameObject> list = new List<GameObject>();
		List<List<BMRecycler>> list2 = new List<List<BMRecycler>>();
		if (itemName == null)
		{
			foreach (List<BMRecycler> item in this.pools.Values)
			{
				list2.Add(item);
			}
		}
		else if (BMPool.Contains(itemName))
		{
			list2.Add(this.pools[itemName.ToLower()]);
		}
		foreach (List<BMRecycler> list3 in list2)
		{
			foreach (BMRecycler bmrecycler in list3)
			{
				if (!bmrecycler.IsPrepared)
				{
					list.Add(bmrecycler.gameObject);
				}
			}
		}
		return list;
	}

	private List<GameObject> _GetUsingItems<T>(string itemName) where T : MonoBehaviour
	{
		List<GameObject> list = new List<GameObject>();
		List<List<BMRecycler>> list2 = new List<List<BMRecycler>>();
		if (itemName == null)
		{
			foreach (List<BMRecycler> item in this.pools.Values)
			{
				list2.Add(item);
			}
		}
		else if (BMPool.Contains(itemName))
		{
			list2.Add(this.pools[itemName.ToLower()]);
		}
		foreach (List<BMRecycler> list3 in list2)
		{
			foreach (BMRecycler bmrecycler in list3)
			{
				if (!bmrecycler.IsPrepared && bmrecycler.GetComponent<T>() != null)
				{
					list.Add(bmrecycler.gameObject);
				}
			}
		}
		return list;
	}

	private void _Abandon(BMRecycler recycler)
	{
		recycler.State = RECYCLE_STATE.ABANDONED;
		this.prepareQueue.Enqueue(recycler);
		recycler.Release();
	}

	private void _Clear()
	{
		foreach (string key in this.pools.Keys)
		{
			foreach (BMRecycler bmrecycler in this.pools[key])
			{
				UnityEngine.Object.Destroy(bmrecycler.gameObject);
			}
			this.pools[key].Clear();
		}
		this.pools.Clear();
		this.molds.Clear();
		Resources.UnloadUnusedAssets();
	}

	public static void ClearPool()
	{
		BMPool.instance._ClearPool();
	}

	private void _ClearPool()
	{
		foreach (string key in this.pools.Keys)
		{
			foreach (BMRecycler bmrecycler in this.pools[key])
			{
				UnityEngine.Object.Destroy(bmrecycler.gameObject);
			}
			this.pools[key].Clear();
		}
	}

	private const string poolSettingsAssetName = "BMPoolSetting";

	private const string poolSettingsPath = "Resources";

	private const string poolSettingsAssetExtension = ".asset";

	public GameObject[] prefabs;

	public string prefabPath = string.Empty;

	private static BMPool instance;

	public static bool initialized;

	private Dictionary<string, GameObject> molds = new Dictionary<string, GameObject>();

	private Dictionary<string, List<BMRecycler>> pools = new Dictionary<string, List<BMRecycler>>();

	private Queue<BMRecycler> prepareQueue = new Queue<BMRecycler>();
}
